"""****************************************************************************************
 ** FileName:        Aes_math.py
 ** Author:          Jiawei Hawkins
 ** Date:            2019-04-03 星期三 14:24:10
 ** Description:     实现Aes所需要的数学基础
 ****************************************************************************************"""

from math import log2

"""****************************************************************************************
 ** Date:            2019-04-03 星期三 14:25:09
 ** Description:     GF(2^8)上的运算            输入输出为2位16进制字符串, 不带标识符0x，0b
 ****************************************************************************************"""


m_8 = 0b100011011                                      #GF(2^8)上的8次不可约多项式

sheet_gf = [
    '01', '03', '05', '0f', '11', '33', '55', 'ff', '1a', '2e', '72', 
    '96', 'a1', 'f8', '13', '35', '5f', 'e1', '38', '48', 'd8', '73', 
    '95', 'a4', 'f7', '02', '06', '0a', '1e', '22', '66', 'aa', 'e5', 
    '34', '5c', 'e4', '37', '59', 'eb', '26', '6a', 'be', 'd9', '70', 
    '90', 'ab', 'e6', '31', '53', 'f5', '04', '0c', '14', '3c', '44', 
    'cc', '4f', 'd1', '68', 'b8', 'd3', '6e', 'b2', 'cd', '4c', 'd4', 
    '67', 'a9', 'e0', '3b', '4d', 'd7', '62', 'a6', 'f1', '08', '18', 
    '28', '78', '88', '83', '9e', 'b9', 'd0', '6b', 'bd', 'dc', '7f', 
    '81', '98', 'b3', 'ce', '49', 'db', '76', '9a', 'b5', 'c4', '57', 
    'f9', '10', '30', '50', 'f0', '0b', '1d', '27', '69', 'bb', 'd6', 
    '61', 'a3', 'fe', '19', '2b', '7d', '87', '92', 'ad', 'ec', '2f', 
    '71', '93', 'ae', 'e9', '20', '60', 'a0', 'fb', '16', '3a', '4e', 
    'd2', '6d', 'b7', 'c2', '5d', 'e7', '32', '56', 'fa', '15', '3f', 
    '41', 'c3', '5e', 'e2', '3d', '47', 'c9', '40', 'c0', '5b', 'ed', 
    '2c', '74', '9c', 'bf', 'da', '75', '9f', 'ba', 'd5', '64', 'ac', 
    'ef', '2a', '7e', '82', '9d', 'bc', 'df', '7a', '8e', '89', '80', 
    '9b', 'b6', 'c1', '58', 'e8', '23', '65', 'af', 'ea', '25', '6f', 
    'b1', 'c8', '43', 'c5', '54', 'fc', '1f', '21', '63', 'a5', 'f4', 
    '07', '09', '1b', '2d', '77', '99', 'b0', 'cb', '46', 'ca', '45', 
    'cf', '4a', 'de', '79', '8b', '86', '91', 'a8', 'e3', '3e', '42', 
    'c6', '51', 'f3', '0e', '12', '36', '5a', 'ee', '29', '7b', '8d', 
    '8c', '8f', '8a', '85', '94', 'a7', 'f2', '0d', '17', '39', '4b', 
    'dd', '7c', '84', '97', 'a2', 'fd', '1c', '24', '6c', 'b4', 'c7', 
    '52', 'f6'
]


def mod_gf(n):
    n = int(n, 16)
    length = len(bin(n)) - 3                #实际长度 - 1
    while( length > 7):
        if( ( (m_8>>length) & 1) == 1):
            n = n ^ m_8
        length = length - 1
    return (hex(n)[2:]).zfill(2)


def add_gf(n, m):
    n = int(n, 16)
    m = int(m, 16)
    return mod_gf(hex(n ^ m))

# sheet_gf[0] = '01'                                                      #生成表
# for i in range(2, 2 ** 8):
#     sheet_gf.append( add_gf( (int(num_8[i - 2], 16) << 1), num_8[i - 2] ) )


def mul_gf(n, m):
    if( int(n, 16) == 0 or int(m, 16) == 0):
        return '00'
    return sheet_gf[ (sheet_gf.index(n) + sheet_gf.index(m) ) % 255]


def inv_gf(n):
    if(int(n, 16) == 0 or int(n, 16) == 1):
        return n
    return sheet_gf[255 - sheet_gf.index(n)]



"""****************************************************************************************
 ** Date:            2019-04-03 星期三 15:11:21
 ** Description:     s盒及其查询
 ****************************************************************************************"""


# s_box = [['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f'], ['10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f'], ['20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f'], ['30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f'], ['40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f'], ['50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f'], ['60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f'], ['70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f'], ['80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f'], ['90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f'], ['a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af'], ['b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf'], ['c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf'], ['d0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df'], ['e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef'], ['f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff']]
# s_box = [['00', '01', '8d', 'f6', 'cb', '52', '7b', 'd1', 'e8', '4f', '29', 'c0', 'b0', 'e1', 'e5', 'c7'], ['74', 'b4', 'aa', '4b', '99', '2b', '60', '5f', '58', '3f', 'fd', 'cc', 'ff', '40', 'ee', 'b2'], ['3a', '6e', '5a', 'f1', '55', '4d', 'a8', 'c9', 'c1', '0a', '98', '15', '30', '44', 'a2', 'c2'], ['2c', '45', '92', '6c', 'f3', '39', '66', '42', 'f2', '35', '20', '6f', '77', 'bb', '59', '19'], ['1d', 'fe', '37', '67', '2d', '31', 'f5', '69', 'a7', '64', 'ab', '13', '54', '25', 'e9', '09'], ['ed', '5c', '05', 'ca', '4c', '24', '87', 'bf', '18', '3e', '22', 'f0', '51', 'ec', '61', '17'], ['16', '5e', 'af', 'd3', '49', 'a6', '36', '43', 'f4', '47', '91', 'df', '33', '93', '21', '3b'], ['79', 'b7', '97', '85', '10', 'b5', 'ba', '3c', 'b6', '70', 'd0', '06', 'a1', 'fa', '81', '82'], ['83', '7e', '7f', '80', '96', '73', 'be', '56', '9b', '9e', '95', 'd9', 'f7', '02', 'b9', 'a4'], ['de', '6a', '32', '6d', 'd8', '8a', '84', '72', '2a', '14', '9f', '88', 'f9', 'dc', '89', '9a'], ['fb', '7c', '2e', 'c3', '8f', 'b8', '65', '48', '26', 'c8', '12', '4a', 'ce', 'e7', 'd2', '62'], ['0c', 'e0', '1f', 'ef', '11', '75', '78', '71', 'a5', '8e', '76', '3d', 'bd', 'bc', '86', '57'], ['0b', '28', '2f', 'a3', 'da', 'd4', 'e4', '0f', 'a9', '27', '53', '04', '1b', 'fc', 'ac', 'e6'], ['7a', '07', 'ae', '63', 'c5', 'db', 'e2', 'ea', '94', '8b', 'c4', 'd5', '9d', 'f8', '90', '6b'], ['b1', '0d', 'd6', 'eb', 'c6', '0e', 'cf', 'ad', '08', '4e', 'd7', 'e3', '5d', '50', '1e', 'b3'], ['5b', '23', '38', '34', '68', '46', '03', '8c', 'dd', '9c', '7d', 'a0', 'cd', '1a', '41', '1c']]
# for i in range(0, 16):
#     for j in range(0, 16):
#         c = list('01100011')
#         c.reverse()
#         b = list( (bin( int(s_box[i][j], 16) )[2:]).zfill(8) )
#         b.reverse()

#         res = ''
#         for k in range(8):
#             res =chr(( ord(b[k]) - 48 ) ^ ( ord(b[(k + 4)%8]) - 48 ) ^ ( ord(b[(k + 5)%8]) - 48 ) ^ ( ord(b[(k + 6)%8]) - 48 ) ^ ( ord(b[(k + 7)%8]) - 48 ) ^ (ord(c[k]) - 48)+ 48) + res
#         s_box[i][j] ='' + (hex(int(res, 2))[2:]).zfill(2)

s_box = [
    ['63', '7c', '77', '7b', 'f2', '6b', '6f', 'c5', '30', '01', '67', '2b', 'fe', 'd7', 'ab', '76'], 
    ['ca', '82', 'c9', '7d', 'fa', '59', '47', 'f0', 'ad', 'd4', 'a2', 'af', '9c', 'a4', '72', 'c0'], 
    ['b7', 'fd', '93', '26', '36', '3f', 'f7', 'cc', '34', 'a5', 'e5', 'f1', '71', 'd8', '31', '15'], 
    ['04', 'c7', '23', 'c3', '18', '96', '05', '9a', '07', '12', '80', 'e2', 'eb', '27', 'b2', '75'], 
    ['09', '83', '2c', '1a', '1b', '6e', '5a', 'a0', '52', '3b', 'd6', 'b3', '29', 'e3', '2f', '84'], 
    ['53', 'd1', '00', 'ed', '20', 'fc', 'b1', '5b', '6a', 'cb', 'be', '39', '4a', '4c', '58', 'cf'], 
    ['d0', 'ef', 'aa', 'fb', '43', '4d', '33', '85', '45', 'f9', '02', '7f', '50', '3c', '9f', 'a8'], 
    ['51', 'a3', '40', '8f', '92', '9d', '38', 'f5', 'bc', 'b6', 'da', '21', '10', 'ff', 'f3', 'd2'], 
    ['cd', '0c', '13', 'ec', '5f', '97', '44', '17', 'c4', 'a7', '7e', '3d', '64', '5d', '19', '73'], 
    ['60', '81', '4f', 'dc', '22', '2a', '90', '88', '46', 'ee', 'b8', '14', 'de', '5e', '0b', 'db'], 
    ['e0', '32', '3a', '0a', '49', '06', '24', '5c', 'c2', 'd3', 'ac', '62', '91', '95', 'e4', '79'], 
    ['e7', 'c8', '37', '6d', '8d', 'd5', '4e', 'a9', '6c', '56', 'f4', 'ea', '65', '7a', 'ae', '08'], 
    ['ba', '78', '25', '2e', '1c', 'a6', 'b4', 'c6', 'e8', 'dd', '74', '1f', '4b', 'bd', '8b', '8a'], 
    ['70', '3e', 'b5', '66', '48', '03', 'f6', '0e', '61', '35', '57', 'b9', '86', 'c1', '1d', '9e'], 
    ['e1', 'f8', '98', '11', '69', 'd9', '8e', '94', '9b', '1e', '87', 'e9', 'ce', '55', '28', 'df'], 
    ['8c', 'a1', '89', '0d', 'bf', 'e6', '42', '68', '41', '99', '2d', '0f', 'b0', '54', 'bb', '16']
]

# res = []
# for i in range(16):
#     res.append([0] * 16)
# for i in range(16):
#     for j in range(16):
#         row_inv = int(s_box[i][j][:1], 16)
#         col_inv = int(s_box[i][j][1:], 16)
#         res[row_inv][col_inv] = (hex(i)[2:]).zfill(1) + (hex(j)[2:]).zfill(1)

s_box_inv = [
    ['52', '09', '6a', 'd5', '30', '36', 'a5', '38', 'bf', '40', 'a3', '9e', '81', 'f3', 'd7', 'fb'], 
    ['7c', 'e3', '39', '82', '9b', '2f', 'ff', '87', '34', '8e', '43', '44', 'c4', 'de', 'e9', 'cb'], 
    ['54', '7b', '94', '32', 'a6', 'c2', '23', '3d', 'ee', '4c', '95', '0b', '42', 'fa', 'c3', '4e'], 
    ['08', '2e', 'a1', '66', '28', 'd9', '24', 'b2', '76', '5b', 'a2', '49', '6d', '8b', 'd1', '25'], 
    ['72', 'f8', 'f6', '64', '86', '68', '98', '16', 'd4', 'a4', '5c', 'cc', '5d', '65', 'b6', '92'], 
    ['6c', '70', '48', '50', 'fd', 'ed', 'b9', 'da', '5e', '15', '46', '57', 'a7', '8d', '9d', '84'], 
    ['90', 'd8', 'ab', '00', '8c', 'bc', 'd3', '0a', 'f7', 'e4', '58', '05', 'b8', 'b3', '45', '06'], 
    ['d0', '2c', '1e', '8f', 'ca', '3f', '0f', '02', 'c1', 'af', 'bd', '03', '01', '13', '8a', '6b'], 
    ['3a', '91', '11', '41', '4f', '67', 'dc', 'ea', '97', 'f2', 'cf', 'ce', 'f0', 'b4', 'e6', '73'], 
    ['96', 'ac', '74', '22', 'e7', 'ad', '35', '85', 'e2', 'f9', '37', 'e8', '1c', '75', 'df', '6e'], 
    ['47', 'f1', '1a', '71', '1d', '29', 'c5', '89', '6f', 'b7', '62', '0e', 'aa', '18', 'be', '1b'], 
    ['fc', '56', '3e', '4b', 'c6', 'd2', '79', '20', '9a', 'db', 'c0', 'fe', '78', 'cd', '5a', 'f4'], 
    ['1f', 'dd', 'a8', '33', '88', '07', 'c7', '31', 'b1', '12', '10', '59', '27', '80', 'ec', '5f'], 
    ['60', '51', '7f', 'a9', '19', 'b5', '4a', '0d', '2d', 'e5', '7a', '9f', '93', 'c9', '9c', 'ef'], 
    ['a0', 'e0', '3b', '4d', 'ae', '2a', 'f5', 'b0', 'c8', 'eb', 'bb', '3c', '83', '53', '99', '61'], 
    ['17', '2b', '04', '7e', 'ba', '77', 'd6', '26', 'e1', '69', '14', '63', '55', '21', '0c', '7d']
]